tg-me.com/sqlhub/1877
Last Update:
🧠 SQL-задача с подвохом: “Самый активный — или самый невидимый?”
📘 Условие
У тебя есть две таблицы:
users(id, name)
posts(id, user_id, title)
Вопрос:
Выведи всех пользователей, у которых нет ни одного поста,
а также пользователя, у которого больше всего постов.
📌 Но — в одном запросе.
❓ Попробуй решить задачу таким SQL:
SELECT u.name, COUNT(p.id) AS post_count
FROM users u
LEFT JOIN posts p ON u.id = p.user_id
GROUP BY u.name
HAVING COUNT(p.id) = 0 OR COUNT(p.id) = (
SELECT MAX(cnt)
FROM (
SELECT COUNT(*) AS cnt
FROM posts
GROUP BY user_id
) t
);
🔍 Вопрос:
1) Почему он может вернуть неправильный результат?
2) В чём разница между
COUNT(*)
и COUNT(p.id)
? 3) Как переписать его правильно?
✅ Разбор подвоха
💣 Подвох 1:
COUNT(p.id)
пропускает NULL
Когда ты делаешь
LEFT JOIN
, для пользователей без постов p.id = NULL
.•
COUNT(*)
считает все строки (включая NULL) •
COUNT(p.id)
не считает строки, где p.id IS NULL
👉 Это может привести к тому, что:
•
COUNT(p.id) = 0
— действительно "нет постов" • но в подзапросе
SELECT COUNT(*)
считает иначе и даёт искаженную MAX(cnt)
🔁 Как правильно:
1) Подзапрос должен использовать
COUNT(p.id)
, чтобы сравнение было честным 2) Либо использовать
JOIN
вместо LEFT JOIN
в подзапросе, чтобы не попасть на "нулевых" пользователей✅ Финальный корректный запрос:
SELECT u.name, COUNT(p.id) AS post_count
FROM users u
LEFT JOIN posts p ON u.id = p.user_id
GROUP BY u.name
HAVING COUNT(p.id) = 0
OR COUNT(p.id) = (
SELECT MAX(cnt)
FROM (
SELECT user_id, COUNT(p.id) AS cnt
FROM posts
GROUP BY user_id
) AS ranked
);
🎯 Такой запрос честно покажет:
• Всех “молчунов” (0 постов)
• И самого активного автора (макс постов)
📌 Отлично подходит для собеседования или тех, кто считает, что "GROUP BY — это просто".
@sqlhub
BY Data Science. SQL hub
Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283
Share with your friend now:
tg-me.com/sqlhub/1877